package com.sunchp.nio.sample.reactor;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ReactorServer {
    private ExecutorService executorService;
    private Selector selector;
    private ServerSocketChannel serverSocketChannel;
    private ThreadPoolHandler threadPoolHandler;

    public ReactorServer(ExecutorService executorService) {
        this.executorService = executorService;
    }

    public void serve() {
        try {
            this.threadPoolHandler = new ThreadPoolHandler(executorService);
            this.selector = Selector.open();
            this.serverSocketChannel = ServerSocketChannel.open();
            this.serverSocketChannel.configureBlocking(false);
            this.serverSocketChannel.socket().bind(new InetSocketAddress(8080));
            this.serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT, new Acceptor(this.selector, threadPoolHandler));

            while (true) {
                this.selector.select();
                Set<SelectionKey> selectionKeys = this.selector.selectedKeys();

                for (SelectionKey selectionKey : selectionKeys) {
                    Handler handler = (Handler) selectionKey.attachment();
                    if (handler != null) {
                        handler.handle(selectionKey);
                    }
                }

                selectionKeys.clear();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        new ReactorServer(Executors.newFixedThreadPool(4)).serve();
    }
}
